package org.joshsacks.fishies.ui.gl;

import static javax.microedition.khronos.opengles.GL10.GL_TEXTURE_ENV;
import static javax.microedition.khronos.opengles.GL10.GL_TEXTURE_ENV_MODE;

import java.util.HashMap;
import java.util.Map;

import javax.microedition.khronos.opengles.GL10;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Rect;
import android.opengl.GLUtils;

public class Font {
  private static final String CHARS =
    "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ .-()+=:";
   
  private Map<Character, Float> charPosition = new HashMap<Character, Float>();
  private Map<Character, Float> charWidth = new HashMap<Character, Float>();
  private int texture;
  private int textHeight;
  private final Bitmap bitmap;
  private final int fontSize;  
  
  public Font(int fontSize, GL10 gl) {
    this.fontSize = fontSize;
    // Draw the text
    Paint textPaint = new Paint();
    textPaint.setTextSize(fontSize);
    textPaint.setAntiAlias(true);
    textPaint.setARGB(0xFF, 0xff, 0xff, 0xFF);
    textPaint.setTextAlign(Align.LEFT);
    Rect bounds = new Rect();
    textPaint.getTextBounds(CHARS, 0, CHARS.length(), bounds);
    int totalWidth = bounds.width();
    textHeight = bounds.height();
    bitmap = Bitmap.createBitmap(
            totalWidth, textHeight, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    bitmap.eraseColor(0x00000000);

    // draw the text centered
    canvas.drawText(CHARS, 0, textHeight, textPaint);    
    setCharPositions(textPaint, totalWidth);
    init(gl);
  }
  
  public void init(GL10 gl) {
    System.err.println("FONT INIT CALLED");
    renderTexture(gl, bitmap);
  }

  private void setCharPositions(Paint textPaint, float totalWidth) {
    for (int i = 0; i < CHARS.length(); i++) {
      Character c = CHARS.charAt(i);
      float position = textPaint.measureText(CHARS, 0, i);
      float width = (textPaint.measureText(CHARS, 0, i + 1) - position);
      charPosition.put(c, position / totalWidth);
      charWidth.put(c, width / totalWidth);      
    }
  }

  private void renderTexture(GL10 gl, Bitmap bitmap) {
    int[] textureArray = new int[1];
    //Generate one texture pointer...
    gl.glGenTextures(1, textureArray, 0);
    texture = textureArray[0];
    //...and bind it to our array
    gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);

    //Create Nearest Filtered Texture
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

    //Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);

    //Use the Android GLUtils to specify a two-dimensional texture image from our bitmap
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
  }
  
  public int renderText(GL10 gl, String text, float x, float y, 
          TextureManager textureManager) {
    gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);
    gl.glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL10.GL_MODULATE);  
    int width = 0;
    SquareRenderer square = new SquareRenderer(gl);
    for (int i = 0; i < text.length(); i++) {
      width += renderChar(gl, text.charAt(i), x + width, y, square);
    }  
 
    square.draw();
    return width;
  }
  
  private float renderChar(GL10 gl, char c, float x, float y, 
          SquareRenderer square) {
    Float width = charWidth.get(c);
    Float position = charPosition.get(c);
    if (width == null || position == null) {
      System.err.println("No char: " + c);
      return 80;
    }
    float[] textureCoor = new float[4 * 2];
    textureCoor[0] = position;
    textureCoor[1] = 1;

    textureCoor[2] = position;
    textureCoor[3] = 0;

    textureCoor[4] = position + width;
    textureCoor[5] = 0;

    textureCoor[6] = position + width;
    textureCoor[7] = 1;

    square.addRectangle(x, y, (int) (width * fontSize * CHARS.length()),
            textHeight, textureCoor);
    return width * fontSize * CHARS.length();
  }
  
}
